/*
 *
 * FileName: ImportFileReceipt.java
 * Author:   wx:fdzhangc
 * Date:     2021/11/25 18:55
 * Description: //模块目的、功能描述
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名    修改时间    版本号       描述
 */
package easyexcel.importexcel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.google.common.collect.Lists;
import easyexcel.TestExecuteSerivceImpl;
import easyexcel.controller.FileBean;
import easyexcel.controller.FileExecuteParam;
import lombok.extern.slf4j.Slf4j;

/**
 * 功能描述:<br>
 *
 * @author wx:fdzhangc
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Slf4j
@Service
public class ImportFileReceipt {
    @Autowired
    TestExecuteSerivceImpl testExecuteSerivce;
    @Autowired
    private LineExtendFactory lineExtendFactory;

    private class EasyWriteTable extends WriteTable {
        private EasyWriteTable(Integer tableNo, List<List<String>> header) {
            setTableNo(tableNo);
            setHead(header);
        }
    }

    public String importNormal(FileBean fileBean, FileExecuteParam fileExecuteParam, ImportConfigBean configBean, String remoteUser) {
        //OSSBean ossBean = new OSSBean(fileExecuteParam.getBizType(), fileExecuteParam.getTaskType(), new Date());
        ImportTaskBean importTaskBean = new ImportTaskBean();
        importTaskBean.setFileName(fileBean.getFileName());
        importTaskBean.setFileFormat(fileBean.getFileFormat());
        importTaskBean.setBizType(fileExecuteParam.getBizType());
        importTaskBean.setTaskType(fileExecuteParam.getTaskType());
        importTaskBean.setTaskTime(new Date());
        importTaskBean.setTaskStatus(1);
        importTaskBean.setTerm(fileExecuteParam.getTerm());
        //文件上传到oss
        //importTaskBean.setFileObjectId(ossFileAdapter.uploadFile(fileBean.getInputStream(), fileBean.getOriginalFileName(), fileBean.getContentType(), ossBean));
        importTaskBean.setCreator(remoteUser);
        importTaskBean.setUpdater(remoteUser);
        Long pkId = 1L;
        //importTaskDao.insertPk(importTaskBean);
        //异步去做：丢到线程池中、mq
        testExecuteSerivce.load(fileExecuteParam.getBizType(), fileExecuteParam.getTaskType(), pkId);
        return "上传任务生成成功，请去上传中心查看";
    }

    public String importSplit(FileBean fileBean, FileExecuteParam fileExecuteParam, ImportConfigBean configBean, String remoteUser) throws
            IOException {
        // 文件分割索引
        final AtomicInteger fileIndex = new AtomicInteger(0);

        // 当前行数
        final AtomicInteger currLine = new AtomicInteger(0);

        final LineExtendHandle lineExtendHandle = lineExtendFactory.getLineExtendHandle(configBean.getSplitHandle());

        EasyExcel.read(fileBean.getInputStream(), new AnalysisEventListener() {

            private final Integer batch = 1000;

            private List<List<Object>> rowList = new ArrayList<>(batch);

            private List<List<String>> headerList = getHeaderList(configBean.getHeaderLine());

            private File temp = File.createTempFile(getNewFileName(fileIndex, fileBean), fileBean.getFileFormat());

            private ExcelWriter excelWriter = EasyExcel.write(temp).build();

            private WriteTable writeTable = new EasyWriteTable(0, headerList);

            private WriteSheet writeSheet = EasyExcel.writerSheet(0, "split").build();

            @Override
            public void invoke(Object data, AnalysisContext context) {

                if (currLine.get() >= configBean.getSplitLine()) {
                    excelWriter.finish();
                    //
                    try {
                        importNormal(new FileBean(getNewFileName(fileIndex, fileBean), fileBean.getFileFormat(), fileBean.getContentType(),
                                new FileInputStream(temp)), fileExecuteParam, configBean, remoteUser);
                    } catch (FileNotFoundException e) {
                        log.error("", e);
                    }
                    fileIndex.set(fileIndex.get() + 1);
                    currLine.set(0);
                    temp.delete();

                    //
                    try {
                        temp = File.createTempFile(getNewFileName(fileIndex, fileBean), fileBean.getFileFormat());
                    } catch (IOException e) {
                        log.error("", e);
                    }
                    excelWriter = EasyExcel.write(temp).build();
                }

                // 由于扩展数据的原因 可能导致 rowList的值大于 写入excel批次的值
                if (rowList.size() >= batch) {
                    excelWriter.write(rowList, writeSheet, writeTable);
                    rowList.clear();
                }

                List<Object> row = Lists.newArrayList();
                Map rowMap = (Map) data;
                for (Object entry : rowMap.entrySet()) {
                    row.add(((Map.Entry) entry).getValue());
                }
                // 单行扩展成多行
                List<List<Object>> extendList = lineExtendHandle.apply(row);
                currLine.set(currLine.get() + extendList.size());
                rowList.addAll(extendList);
            }

            private List<List<String>> getHeaderList(int headerLine) {
                List<List<String>> headerList = Lists.newArrayList();
                for (int i = 0; i < headerLine; i++) {
                    headerList.add(Lists.newArrayList());
                }
                return headerList;
            }

            private String getNewFileName(AtomicInteger fileIndex, FileBean fileBean) {
                return fileBean.getFileName() + "_" + fileIndex.get();
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 兜底 最后一部分数据 直接追加到最后一个文件,不再新增文件
                if (CollectionUtils.isNotEmpty(rowList)) {
                    excelWriter.write(rowList, writeSheet, writeTable);
                    excelWriter.finish();
                    try {
                        importNormal(new FileBean(getNewFileName(fileIndex, fileBean), fileBean.getFileFormat(), fileBean.getContentType(),
                                new FileInputStream(temp)), fileExecuteParam, configBean, remoteUser);
                    } catch (FileNotFoundException e) {
                        log.error("", e);
                    }
                    temp.delete();
                }
            }

            // 推荐复写这个方法 原因在于headMap为linkedHashMap
            @Override
            public void invokeHead(Map headMap, AnalysisContext context) {

                for (Object object : headMap.entrySet()) {
                    Map.Entry entry = (Map.Entry) object;
                    Integer colIndex = (Integer) entry.getKey();
                    headerList.get(colIndex).add(((CellData) entry.getValue()).getStringValue());
                }
                super.invokeHead(headMap, context);
            }
        }).headRowNumber(configBean.getHeaderLine()).sheet().doRead();
        return "上传任务生成成功，请去上传中心查看";
    }
}
